package controllers;

import interceptors.DefaultInterceptor;
import interceptors.UserSessionInterceptor;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Map;

import collectors.people.util.Config;
import models.User;
import play.Play;
import play.cache.Cache;
import play.libs.F;
import play.libs.F.Function;
import play.libs.F.Promise;
import play.libs.WS;
import play.libs.WS.Response;
import play.libs.WS.WSRequest;
import play.mvc.Controller;
import play.mvc.Result;
import play.mvc.With;
import services.UserService;
import util.UserSession;
import exceptions.FilYOUInstalationException;

@With({DefaultInterceptor.class, UserSessionInterceptor.class})
public class Application extends Controller {

	private static final UserService userService = UserService.getInstance();

	public static Result index() {

		String uuid = session("uuid");
		UserSession userSession = (UserSession) Cache.get(uuid + "_user");
		User user = userSession.getUser();
		if (user == null) {
			return ok(views.html.index.render());
		} else {
			return redirect(routes.Search.index());
		}
	}

	/**
	 * Logs out of the system and renders login form
	 * 
	 * @return login view form
	 */
	public static Result signout() {
		String uuid = session("uuid");
		Cache.remove(uuid + "_user");
		session().clear();
		return redirect(routes.Application.index());
	}


	public static Result signin() {
		try {
			Map<String, String[]> params = request().body().asFormUrlEncoded();

			String[] username = params.get("username");
			String[] password = params.get("password");

			if(username[0] != null && !username[0].equals("") && password[0] != null && !password[0].equals("")){

				userService.createOrSignin(username[0], password[0], session());

				return redirect(routes.Search.index());
			}else{
				return badRequest();
			}

		} catch (FilYOUInstalationException e) {
			e.printStackTrace();
			return internalServerError("Error installing user on Filyou");
		}
	}
	
	public static Result redirectToFacebook() throws UnsupportedEncodingException  {
		String fbid = Play.application().configuration().getString("you.fbkey");
		String callback = getCallback();
		String fbredirect = Play.application().configuration().getString("you.fblogin");
		fbredirect = fbredirect.replace("$ID$", fbid);
		fbredirect = fbredirect.replace("$REDIRECT$", URLEncoder.encode(callback, "UTF-8"));
		return redirect(fbredirect);
	}
	
	private static String getCallback() {
		String callback = controllers.routes.Application
				.facebookSignin("","").absoluteURL(request());
		callback = callback.substring(0,callback.indexOf('?'));
		return callback;
	}
	
	public static Result facebookSignin(String code, String state) throws UnsupportedEncodingException {
		// TODO check for CSRF
		
		String fbcode = Play.application().configuration()
				.getString("you.fbcode");
		String fbid = Play.application().configuration().getString("you.fbkey");
		String fbsecret = Play.application().configuration().getString("you.fbsecret");
		
		Promise<Response> codeRequest = WS.url(fbcode)
				.setQueryParameter("redirect_uri", getCallback())
				.setQueryParameter("client_id", fbid)
				.setQueryParameter("client_secret", fbsecret)
				.setQueryParameter("code", code)
				.get();
		return async(codeRequest.map(new Function<WS.Response, Result>() {
			@Override
			public Result apply(Response response) throws Throwable {
				String result = response.getBody();
				int accessStart = result.indexOf('=') + 1;
				int accessEnd = result.indexOf('&');
				String token = result.substring(accessStart,accessEnd);
				
				String fbdebug = Play.application().configuration()
						.getString("you.fbdebug");
				String fbtoken = Play.application().configuration()
						.getString("you.fbaccess");
				fbdebug = fbdebug.replace("$TOKEN$", token);
				Promise<Response> debugRequest = WS.url(fbdebug)
						.setQueryParameter("input_token", token)
						.setQueryParameter("access_token", fbtoken)
						.get();
				return async(debugRequest.map(new Function<WS.Response, Result>() {
					@Override
					public Result apply(Response arg0) throws Throwable {
						String userId = arg0.asJson().get("data").get("user_id")
								.asText();
						System.out.println("fbuserid = " + userId);
						userService.createOrSigninFacebook(userId, session());
						return redirect(routes.Search.index());
					}
				}));
			}
		}));
	}

	/**
	 * Logs out of the system and renders login form
	 * 
	 * @return login view form
	 */
	public static Result logout() {
		String uuid = session("uuid");
		Cache.remove(uuid + "_user");
		session().clear();
		return redirect(routes.Application.index());
	}
}
